package com.jurenzhao.partssystem.system.system_log.aspect;

import com.jurenzhao.partssystem.system.system_log.aspect.annotation.SystemControllerLog;
import com.jurenzhao.partssystem.system.system_log.aspect.annotation.SystemServiceLog;
import com.jurenzhao.partssystem.system.system_log.entity.System_Log;
import com.jurenzhao.partssystem.system.system_log.service.LogService;
import com.jurenzhao.partssystem.system.system_log.util.Constants;
import com.jurenzhao.partssystem.system.system_log.util.JSONUtil;
import com.jurenzhao.partssystem.system.system_user.entity.System_Users;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
import java.util.Date;


    /**
     * 系统日志 切点类
     *
     * 暂时停用
     *
     *
     * @author boge
     *
     */

    @Aspect
    @Component
    public class SystemLogAspect {
        //注入Service用于把日志保存数据库
        @Resource
        private LogService logService;

        //本地异常日志记录对象
        private static final Logger logger=Logger.getLogger(SystemLogAspect.class);

        //Service层切点
        @Pointcut
                ("@annotation(com.jurenzhao.partssystem.system.system_log.aspect.annotation.SystemServiceLog)")
        public void serviceAspect() {    }

        //Controller层切点
        @Pointcut("@annotation(com.jurenzhao.partssystem.system.system_log.aspect.annotation.SystemControllerLog)")
        public void controllerAspect() {    }

        /**
         * 前置通知 用于拦截Controller层记录用户的操作
         *
         * @param joinPoint 切点
         */
        @Before("controllerAspect()")
        public  void doBefore(JoinPoint joinPoint) {
            System.out.println("进入到 controllerAspect 的 前置通知 方法");

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            HttpSession session = request.getSession();
            //读取session中的用户

            System_Users system_users=(System_Users) session.getAttribute(Constants.CURRENT_USER);
            //请求的IP
            String ip = request.getRemoteAddr();
            try {
                 System.out.println("=====前置通知开始=====");
                System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));
                System.out.println("请求人:" + system_users.getUserName());
                System.out.println("请求IP:" + ip);
                System_Log log=new System_Log();
                log.setLogInfo(getControllerMethodDescription(joinPoint));
                log.setLogState((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
                log.setLogType("0");
                log.setLogIp(ip);
                log.setLogDate(new Date());
                log.setLogUser(system_users.getUserName());

                //保存数据库
                logService.insert(log);
                System.out.println("=====前置通知结束=====");

            }
            catch (Exception e){
                //记录本地异常日志
                logger.error("== 前置通知异常 ==");
                logger.error("异常信息:" + e.getMessage());
            }
        }
        /**
         * 异常通知 用于拦截service层记录异常日志
         *
         * @param joinPoint
         * @param e
         */
        @AfterThrowing(pointcut ="serviceAspect()", throwing = "e")
        public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            HttpSession session = request.getSession();
            //读取session中的用户
            //读取session中的用户
            System_Users system_users = (System_Users) session.getAttribute(Constants.CURRENT_USER);
            //获取请求ip
            String ip = request.getRemoteAddr();
            //获取用户请求方法的参数并序列化为JSON格式字符串
            String params = "";
            if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {
                for ( int i = 0; i < joinPoint.getArgs().length; i++) {
                    params += JSONUtil.toJson(joinPoint.getArgs()[i]) + ";";
                }
            }
            try {
                System.out.println("=====异常通知开始=====");
                System.out.println("异常代码:" + e.getClass().getName());
                System.out.println("异常信息:" + e.getMessage());
                System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
                System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));
                System.out.println("请求人:" + system_users.getUserName());
                System.out.println("请求IP:" + ip);
                System.out.println("请求参数:" + params);


            /*==========数据库日志=========*/
                System_Log log = new System_Log();
                log.setLogInfo(getServiceMthodDescription(joinPoint));

                log.setLogType("1");
                log.setLogInfo(e.getMessage());
                log.setLogUser((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
                log.setLogState(params);
                log.setLogDate(new Date());
                log.setLogIp(ip);
                log.setLogUser(system_users.getUserName());
                //保存数据库
                logService.insert(log);
                System.out.println("=====异常通知结束=====");
            }catch (Exception ex) {
                //记录本地异常日志
                logger.error("==异常通知异常==");
                logger.error("异常信息:" + ex.getMessage());
            }
        /*==========记录本地异常日志==========*/
            logger.error("异常方法:" + joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName()
                    + "异常代码:" + e.getClass().getName()
                    +"异常信息:" + e.getMessage()
                    +"参数:" + params);

        }
        /**
         * 获取注解中对方法的描述信息 用于service层注解
         *
         * @param joinPoint 切点
         * @return 方法描述
         * @throws Exception
         */
        public  static String getServiceMthodDescription(JoinPoint joinPoint)
                throws Exception {
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods = targetClass.getMethods();
            String description = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        description = method.getAnnotation(SystemServiceLog. class).description();
                        break;
                    }
                }
            }
            return description;
        }
        /**
         * 获取注解中对方法的描述信息 用于Controller层注解
         *
         * @param joinPoint 切点
         * @return 方法描述
         * @throws Exception
         */
        public static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {
            System.out.println("进入了 getControllerMethodDescription 方法");
            String targetName = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            Object[] arguments = joinPoint.getArgs();
            Class targetClass = Class.forName(targetName);
            Method[] methods= targetClass.getMethods();
            String description = "";
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {
                        description = method.getAnnotation(SystemControllerLog. class).description();
                        break;
                    }
                }
            }
            return description;
        }
}
